package com.service;

import com.bugs.factory.SpiderFactory;
import com.dao.JobInfoRepository;
import com.dao.utils.JobInfoPredicate;
import com.model.JobInfo;
import com.utils.from.BackJobInfoListForm;
import com.utils.from.FrontJobInfoListForm;
import com.utils.jpa.JpaUtils;
import com.utils.pojo.vo.FrontJobInfoVO;
import org.modelmapper.ModelMapper;
import org.modelmapper.convention.MatchingStrategies;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.Lock;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;


@Service
@Transactional
public class JobInfoService {

    @PersistenceContext
    private EntityManager entityManager;

    @Autowired
    private JobInfoRepository jobInfoRepository;

    public void save(JobInfo jobInfo) {
        Map<String, Object> result = this.isExist(jobInfo);

        if(result == null || result.size() == 0) {
            jobInfoRepository.save(jobInfo);
            SpiderFactory.addSaveDbCount(jobInfo.getWorkBugId());
            System.err.println(jobInfo.getRecruitTitle() + "已被添加.");
        }else {
            Date oldDate = (Date) result.get("releaseDate");
            Date infoDate = Date.from(jobInfo.getReleaseDate().atStartOfDay(ZoneId.systemDefault()).toInstant());
            Integer id = (Integer) result.get("id");
            // 如果数据库资料比爬到的资料旧, 更新数据
            if(oldDate.getTime() < infoDate.getTime()) {
                jobInfo.setId(id.longValue());
                jobInfoRepository.saveAndFlush(jobInfo);
                SpiderFactory.addSaveDbCount(jobInfo.getWorkBugId());
                System.err.println(jobInfo.getRecruitTitle() + "已被更新.");
            }else {
                System.err.println(jobInfo.getRecruitTitle() + " 已被去重.");
            }
        }
    }

    public Map<String, Object> isExist(JobInfo jobInfo) {
        Map<String, Object> result = jobInfoRepository.isExist(jobInfo.getHashcode());
        return result;
    }

    public List<JobInfo> getAllSimpleInfo() {
        List<Map<String, Object>> result = jobInfoRepository.getSimpleData();
        List<JobInfo> jobs = new ArrayList<>(result.size());
        ModelMapper mapper = new ModelMapper();
        mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
        result.forEach(map -> {
            Date date = (Date) map.get("releaseDate");
            JobInfo info = mapper.map(map, JobInfo.class);
            info.setReleaseDateView(date.toString());
            jobs.add(info);
        });
        return jobs;
    }

    public List<JobInfo> searchSimpleInfo(String startDate, String endDate, String title) {
        List<Map<String, Object>> result = jobInfoRepository.searchSimpleInfo(startDate, endDate, title);
        List<JobInfo> jobs = new ArrayList<>(result.size());
        ModelMapper mapper = new ModelMapper();
        mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
        result.forEach(map -> {
            Date date = (Date) map.get("releaseDate");
            JobInfo info = mapper.map(map, JobInfo.class);
            info.setReleaseDateView(date.toString());
            jobs.add(info);
        });
        return jobs;
    }

    public void setHaveRead(Long id) {
        if(id == null) return;
        jobInfoRepository.setHaveRead(id);
    }

    public Page<JobInfo> list(BackJobInfoListForm form) {


        if(form.getCurrentPage() > 0) form.setCurrentPage(form.getCurrentPage() - 1);
        PageRequest pageRequest =  PageRequest.of(form.getCurrentPage(), form.getPageSize());
        Specification specification = (Specification<JobInfo>) (root, query, cb) -> {
            // select 这里无效, JPA不允许分页查询指定select
            query.multiselect(root.get("id")).getRestriction();
            // where
            JobInfoPredicate predicate = new JobInfoPredicate(root, cb, 4);
            predicate   .betweenTime(form.getStartDate(), form.getEndDate())
                        .likeTitle(form.getTitle())
                        .eqReptileClass(form.getReptileClass())
                        .eqJobType(form.getJobType());
            // order
            query.orderBy(cb.desc(root.get("releaseDate")));
            return predicate.setPredicate();
        };
        return jobInfoRepository.findAll(specification, pageRequest);
    }

    public List<FrontJobInfoVO> front_list(FrontJobInfoListForm form) {
        CriteriaBuilder cb = entityManager.getCriteriaBuilder();
        CriteriaQuery<FrontJobInfoVO> cq = cb.createQuery(FrontJobInfoVO.class);
        Root<JobInfo> root = cq.from(JobInfo.class);
        JobInfoPredicate predicate = new JobInfoPredicate(root, cb, 3);
        predicate   .betweenTime(form.getStartDate(), form.getEndDate())
                    .likeTitle(form.getTitle())
                    .eqJobType(form.getJobType());

        cq      .select(JpaUtils.construct(FrontJobInfoVO.class, cb, root))
                .where(predicate.getPredicate())
                .orderBy(cb.desc(root.get("releaseDate")));

        Query query = entityManager.createQuery(cq);
        List<FrontJobInfoVO> result = query.getResultList();
        return result;
    }
}
